package compilador.geradorCodigo;

import java.util.Stack;

import compilador.analisadorLexico.Simbolo;

public class GeradorCodigoImpl implements GeradorCodigo {
	
	private StringBuffer saida = new StringBuffer();
	
	private Stack<String> pcl = new Stack<String>();
	
	private Stack<String> pco = new Stack<String>();
	
	private String ladoEsquerdo;
	
	private Integer numLabel = 0;
	
	private Integer contador;
	
	private String indiceArray = "";

	private String operadorRelacional;
	
	@Override
	public String getCodigo() {
		return saida.toString();
	}
	
	/**
	 * 
	 */
	private void resetTemp() {
		this.contador = 0;
	}
	
	private void resetLabel() {
		this.numLabel = 0;
	}
	
	private void emitir(String op, String operador, String op1, String op2) {
		String out = "";
		
		if (op != null){
			out += op + " ";
		}
		
		out += operador;
		
		if (op1 != null) {
			out += " " + op1;
		}
		
		if (op2 != null) {
			out += " " + op2;
		}
		
		saida.append(out + System.getProperty("line.separator"));
	}
	
	private String makeLabel() {
		return "L" + String.valueOf(++numLabel);
	}
	
	private String makeTemp() {
		return "t" + String.valueOf(++contador);
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraAtribuicao()
	 */
	@Override
	public void acaoGeradoraAtribuicao(Simbolo simbolo) {
		this.ladoEsquerdo = simbolo.getLexema();
		resetTemp();
	}

	
	public void acaoGeradoraExprRelacional(){
		
	}
	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraExpressao()
	 */
	@Override
	public void acaoGeradoraExpressao() {
		String op = pco.pop();
		emitir(ladoEsquerdo, ":= ", op, null);
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraFatorId()
	 */
	@Override
	public void acaoGeradoraFatorId(Simbolo simbolo) {
		pco.push(simbolo.getLexema());
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraNumero()
	 */
	@Override
	public void acaoGeradoraNumero(Simbolo simbolo) {
		pco.push(simbolo.getLexema());
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraTermoSoma()
	 */
	@Override
	public void acaoGeradoraTermo(Simbolo operador) {
		String op2 = pco.pop();
		String op1 = pco.pop();
		
		String id = makeTemp();
		emitir(id, operador.getLexema(), op1, op2);
		pco.push(id);
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoReiniciaTemporarias()
	 */
	@Override
	public void acaoReiniciaTemporarias() {
		resetLabel();
	}
	
	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoSalvaLadoEsquerdo()
	 */
	@Override
	public void acaoGeradoraSalvaLadoEsquerdo() {
		this.ladoEsquerdo = pco.pop();
	}
	
	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoSalvaValorOperador()
	 */
	@Override
	public void acaoGeradoraSalvaValorOperador(Simbolo simbolo) {
		operadorRelacional = simbolo.getLexema();
		System.out.println(operadorRelacional);
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeraTeste()
	 */
	@Override
	public void acaoGeradoraGeraTeste() {
		emitir(null, operadorRelacional, ladoEsquerdo, pco.pop());
		String label = makeLabel();
		pcl.push(label);
		emitir(null, "JNIF", label, null);
	}
	
	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeraEnderecoLabelAnterior()
	 */
	@Override
	public void acaoGeradoraGeraEnderecoLabelAnterior() {
//		String labelAux = pcl.pop();
		pcl.pop();
		String label = makeLabel();
		pcl.push(label);
		emitir(null, "JMP", label, null);
	}
	
	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoResolveEndereco()
	 */
	@Override
	public void acaoGeradoraResolveEnderecoFim() {
		// String label = pcl.pop();
		pcl.pop();
		// insere
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraIniciCiclo()
	 */
	@Override
	public void acaoGeradoraIniciCiclo() {
		resetLabel();
		String label = makeLabel();
		pcl.push(label);
	}
	
	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraFimDeCiclo()
	 */
	@Override
	public void acaoGeradoraFimDeCiclo() {
//		String labelFim = pcl.pop();
		pcl.pop();
		String labelInicio = pcl.pop();
		emitir(null, "JMP", labelInicio, null);
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraSin(compilador.analisadorLexico.Simbolo)
	 */
	@Override
	public void acaoGeradoraAtribuiLadoDireito(Simbolo simbolo) {
		emitir(ladoEsquerdo, ":=", simbolo.getLexema(), null);
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraSout(compilador.analisadorLexico.Simbolo)
	 */
	@Override
	public void acaoGeradoraSout(Simbolo simbolo) {
		emitir(null, "SOUT", simbolo.getLexema(), null);
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraIndiceArray()
	 */
	@Override
	public void acaoGeradoraIndiceArray() {
		indiceArray = pco.pop();
	}

	/* (non-Javadoc)
	 * @see compilador.geradorCodigo.GeradorCodigo#acaoGeradoraAtribuiLadoDireitoArray(compilador.analisadorLexico.Simbolo)
	 */
	@Override
	public void acaoGeradoraAtribuiLadoDireitoArray(Simbolo simbolo) {
		emitir(ladoEsquerdo + "[" + indiceArray + "]", ":=", simbolo.getLexema(), null);
	}
	
}
